import React from 'react';
import FinderCache from "./FinderCache";
import {finderConfApi, queryApi} from "../Config/GlobalApi";
import {forEach, isArray, isBoolean, isEmpty, isFunction, isString, uniq} from "lodash-es";
import {OrderField, QueryDataConf, QueryFilter} from "jh-utils";
import {AcctConfig} from "../Config/FinderConfig";

/**
 * 查找器-辅助类。
 * 封装一些查找器通用的处理逻辑
 */
export default class FinderHelper {

    /**
     *
     * @type {FinderModal | FinderSelectBase | null}
     */
    finderIns = null;
    lastFetchId = 0;

    /**
     * 是否正在请求配置
     * @param value
     */
    set loadingConf(value) {
        FinderCache.loading[this.finderIns.getPropsByName('finderCode')] = value;
    }

    get loadingConf() {
        return FinderCache.loading[this.finderIns.getPropsByName('finderCode')];
    }

    constructor(finderIns) {
        this.finderIns = finderIns;
    }

    /**
     * 获取本地已有的“查找器配置”
     * @param afterCb {function(finderConf: {})}
     */
    getFinderConf(afterCb) {
        const $ins = this.finderIns;

        if (isEmpty($ins.finderConf)) {
            this.fetchConf((rsp) => {
                if (rsp && rsp.status === 200) {
                    afterCb && afterCb($ins.finderConf);
                }
            });
        } else {
            afterCb && afterCb($ins.finderConf);
        }
    }

    /**
     * 发请求获取“查找器配置”
     * @param afterCb {function(rsp: {status: number, data: any})}
     */
    fetchConf(afterCb) {
        const $ins = this.finderIns;
        const finderCode = $ins.getPropsByName('finderCode');

        // 如果当前已经在请求此查找器的配置，则不再请求，将此查找器实例传入 FinderCache，待请求到数据后，再统一更新查找器组件
        if (this.loadingConf) {
            // console.log(`【fetchConf】已经在加载 ${finderCode} 的查找器配置。`, FinderCache)
            FinderCache.addLoadingIns(finderCode, $ins.randomKey, $ins);
            return false;
        } else {
            this.loadingConf = true;

            $ins.setState({loading: true});

            const fetchConf = $ins.getPropsByName('fetchConf');
            const ajaxData = {finderCode};
            const rePromise = isFunction(fetchConf) ? fetchConf(ajaxData) :
                $ins.reqGet(finderConfApi.api, ajaxData);

            if (rePromise instanceof Promise) {
                rePromise.then(rsp => {

                    if (rsp && rsp.status === 200) {
                        $ins.finderConf = rsp.data || {};
                        // FinderCache.addConfCache(finderCode, $ins.finderConf);
                    }
                    this.loadingConf = false;
                    FinderCache.updateInstances(finderCode);

                    $ins.setState({loading: false}, () => {
                        afterCb && afterCb(rsp);
                    });
                });
            } else {
                this.loadingConf = false;
                $ins.setState({loading: false}, afterCb);
            }
        }

    }

    /**
     * 获取 appCode。
     *  如果是多态查找器模型（plural===true），则以 referenceAppInfo.code 作为 appCode 使用。
     *  否则取 props.appCode
     * @return {*}
     */
    getAppCode4Finder() {
        let $ins = this.finderIns;
        let appCode = $ins.getPropsByName('appCode');
        // 如果是多态查找器模型，则以 referenceAppInfo.code 作为 appCode 使用
        let plural = $ins.getPropsByName('plural') || $ins.plural; // 是否多态查找器模型
        if (plural) {
            let referenceAppInfo = $ins.getPropsByName('referenceAppInfo') || $ins.referenceAppInfo; // 关联应用的值
            appCode = referenceAppInfo && referenceAppInfo.code ? referenceAppInfo.code : '';
        }
        return appCode;
    }

    /**
     * 获取“查询查找器列表”需要的参数
     * @param pageSize
     * @param current
     * @return {{ajaxData: any, fetchFunc: null}|boolean}
     */
    getAjaxData4List({pageSize, current}) {
        const $ins = this.finderIns;
        const fetchFunc = this.getFetchListFunc();
        let javaType = $ins.getPropsByName('javaType') || $ins.finderConf.javaType;
        let finderCode = $ins.getPropsByName('finderCode') || $ins.finderConf.finderCode;

        if ((finderCode || javaType) && isFunction(fetchFunc)) {
            let customFinderQueryConf = $ins.getPropsByName('customFinderQueryConf') || $ins.customFinderQueryConf;

            let splitQuery = $ins.getPropsByName('splitQuery') || $ins.splitQuery;
            let queryFields = $ins.getPropsByName('queryFields') || $ins.queryFields;
            let filter = $ins.getPropsByName('filter') || $ins.filter;
            const {fields} = $ins.finderConf;

            const queryConf = new QueryDataConf();
            queryConf.finderCode = finderCode;
            queryConf.javaType = javaType;
            queryConf.splitQuery = splitQuery;
            queryConf.queryFields = !isEmpty(queryFields) ? [...queryFields] : [];
            queryConf.queryFields.push("version");

            // 如果是科目查找器，添加“model”字段
            if (AcctConfig.finderCode === finderCode) {
                queryConf.queryFields.push('model');
            }

            /* 处理查询字段和排序 */
            let orderBy = "ASC";
            let fuzzyMatchArr = $ins.searchData.fuzzyMatch.split(',');

            forEach(fields, (field) => {
                // 支持模糊查询
                if (field.dataType === 'java.lang.String') {
                    fuzzyMatchArr.push(field.fieldName);
                }

                // 查询字段
                if (field.visible) {
                    queryConf.queryFields.push(field.fieldName);
                }
                // 排序
                if (field.sortable) {
                    if (field.orderBy === "DESC") {
                        orderBy = "DESC";
                    } else {
                        orderBy = "ASC";
                    }
                    queryConf.orderFields.push(new OrderField(field.fieldName, orderBy));
                }
            });

            if (current) {
                queryConf.startIndex = (pageSize * (current - 1)) || 0;
                queryConf.maxResults = pageSize
            }

            queryConf.filter = (filter && filter.toJson) ? filter.copy() : new QueryFilter(QueryFilter.AND);

            $ins.searchData.fuzzyMatch = uniq(fuzzyMatchArr).join(',');
            queryConf.filter.formatBySearchData($ins.searchData);

            // 如果是多态查找器模型，则添加 model.javaType 过滤条件
            let plural = $ins.getPropsByName('plural') || $ins.plural; // 是否多态查找器模型
            if (plural) {
                queryConf.filter.andEqual('appCode', this.getAppCode4Finder());
            }

            // 过滤已选中的数据
            if ($ins.filterSelected) {
                let inIds = [];
                forEach($ins.selectedRows, (row) => {
                    if (row && row.id > 0) {
                        inIds.push(row.id);
                    }
                });

                if (!isEmpty(inIds)) {
                    queryConf.filter.andNotIn('id', `(${inIds.join(',')})`);
                }
            }

            isFunction($ins.customQueryConf) && $ins.customQueryConf(queryConf);

            isFunction(customFinderQueryConf) && customFinderQueryConf(queryConf);
            this.setTagFilters(queryConf.filter, javaType);

            const ajaxData = queryConf.toJson();
            ajaxData.filterIns = queryConf.filter;
            ajaxData.searchData = $ins.searchData;
            return {ajaxData, fetchFunc};
        } else {
            return false;
        }

    }

    getFetchListFunc() {
        const $ins = this.finderIns;
        const {appins, fetchList} = $ins.getProps();

        return isFunction(fetchList) ? fetchList : ( // 取 props.fetchList
            // 取 appins.fetchFinder
            appins && appins.fetchFinder ? appins.fetchFinder.bind(appins) :
                this.fetchListFunc.bind(this)
        );
    }

    fetchListFunc(ajaxData) {
        return this.finderIns.request(queryApi, ajaxData);
    }

    /**
     * 设置查找器过滤应用对应的标签值
     * @param filter
     * @param javaType
     */
    setTagFilters(filter, javaType) {
        const $ins = this.finderIns;
        let fieldName = $ins.getPropsByName('fieldName') || ($ins.props && $ins.props.fieldName);
        let belong = $ins.getPropsByName('belong') || {};
        // 集合中的字段名
        if (!isEmpty(belong) && !isEmpty(belong.cellFieldName)) {
            fieldName = belong.cellFieldName;
        }
        let {appins} = $ins.getProps();
        let {filters = []} = appins && appins.tagConfig || {};
        if (filter && fieldName && !isEmpty(filters) && javaType) {
            forEach(filters, item => {
                const filterFn = () => {
                    let {filter: tagFilter} = item;
                    filter.andExists(`(SELECT t.id FROM com.jianhui.conf.domain.AppDataTag t WHERE t.tag.id IN ${tagFilter} AND t.dataId = o.id AND t.javaType = '${javaType}')`)
                };
                if (item.fieldName) {
                    // 如果是集合中查找器字段
                    let nameList = item.fieldName.split('.');
                    if (nameList.length > 1) {
                        let {bodyFieldName} = belong;
                        if (bodyFieldName === nameList[0] && fieldName === nameList[1]) {
                            filterFn()
                        }
                    }
                    if (fieldName === item.fieldName) {
                        filterFn()
                    }
                }
            })
        }
    }
}